package com.neo.push.server.mongo;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import com.neo.push.core.AcceptPush;
import com.neo.push.server.message.MessageMapper;
import com.neo.push.server.message.PushMessageState;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Created by lock on 17-7-31.
 */
public class MongoMessageMapper implements MessageMapper {

    private MongoService mongoService;
    private String collectionName;
    private MongoCollection<Document> messageCollection;
    private Logger logger = LoggerFactory.getLogger(MongoMessageMapper.class);

    public void init(){
        try {
            messageCollection = mongoService.getCollection(collectionName);
            messageCollection.find().forEach((Consumer<Document>) document -> {
                logger.info(" delete message :"+document.toJson());
                messageCollection.deleteOne(document);
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<AcceptPush> loadReceiverOffline(String receiver) {
        List<AcceptPush> pushTexts = new ArrayList<>();
        messageCollection.find(Filters.and(
                Filters.eq("targetName",receiver),
                Filters.or(Filters.eq("state",PushMessageState.SEND.name()),Filters.eq("state",PushMessageState.TIMEOUT.name())))).
                forEach((Consumer<Document>) document -> {
                    logger.info(" offline message "+document.toJson());
                    pushTexts.add(parseDocument(document));
                });
        return pushTexts;
    }

    @Override
    public AcceptPush loadPushMessage(String messageId) {
        Document document = messageCollection.find(Filters.eq("_id",new ObjectId(messageId))).first();
        if(null==document){
            return null;
        }
        return parseDocument(document);
    }

    private AcceptPush parseDocument(Document document){
        AcceptPush text = JSON.parseObject(document.toJson(),AcceptPush.class);
        text.setMessageId(getDocumentId(document));
        return text;
    }

    private String getDocumentId(Document document){
        return document.getObjectId("_id").toHexString();
    }


    /**
     * 更新消息状态
     * @param messageId
     * @param state
     */
    @Override
    public void updateMessageState(String messageId, PushMessageState state) {
        messageCollection.replaceOne(Filters.eq("_id",new ObjectId(messageId)),new Document("state",state.name()));
    }


    @Override
    public AcceptPush savePushMessage(AcceptPush pushMessage) {
        Document document = new Document("content",pushMessage.getContent())
                .append("targetName",pushMessage.getTargetName())
                .append("createTime",pushMessage.getCreateTime())
                .append("pushType",pushMessage.getPushType().name())
                .append("state", PushMessageState.SEND.name());
        messageCollection.insertOne(document);
        pushMessage.setMessageId(getDocumentId(document));
        logger.info(" save message "+document.toJson());
        return pushMessage;
    }


    public void setCollectionName(String collectionName) {
        this.collectionName = collectionName;
    }

    public void setMongoService(MongoService mongoService) {
        this.mongoService = mongoService;
    }

}
